1//////////////////////////////////////////////////////////////////////
  2// LibFile: version.scad
  3//   File that provides functions to manage versioning.
  4// Includes:
  5//   include <BOSL2/std.scad>
  6// FileGroup: Data Management
  7// FileSummary: Parse and compare semantic versions.
  8// FileFootnotes: STD=Included in std.scad
  9//////////////////////////////////////////////////////////////////////
 10
 11
 12BOSL_VERSION = [2,0,716];
 13
 14
 15// Section: BOSL Library Version Functions
 16
 17
 18// Function: bosl_version()
 19// Synopsis: Returns the BOSL2 version as a list.
 20// Topics: Versioning
 21// See Also: bosl_version_num(), bosl_version_str(), bosl_required()
 22// Usage:
 23//   ver = bosl_version();
 24// Description:
 25//   Returns a list with three integer elements, [MAJOR,MINOR,REV],
 26//   representing the Major, Minor, and Build Revision numbers.
 27//   For example, version 2.1.43 will be returned as `[2,1,43]`.
 28function bosl_version() = BOSL_VERSION;
 29
 30
 31// Function: bosl_version_num()
 32// Synopsis: Returns the BOSL2 version as a float.
 33// Topics: Versioning
 34// See Also: bosl_version(), bosl_version_str(), bosl_required()
 35// Usage:
 36//   ver = bosl_version_num();
 37// Description:
 38//   Returns a floating point number of the version, formatted like M.mmrrrr where M is the major version number,
 39//   each m is a zero-padded digit of the minor version number, and each r is a zero-padded digit of the build
 40//   revision number.  For example, version 2.1.43 will be returned as `2.010043`.
 41function bosl_version_num() = version_to_num(BOSL_VERSION);
 42
 43
 44// Function: bosl_version_str()
 45// Synopsis: Returns the BOSL2 version as a string.
 46// Topics: Versioning
 47// See Also: bosl_version(), bosl_version_num(), bosl_required()
 48// Usage:
 49//   ver = bosl_version_str();
 50// Description:
 51//   Returns a string of the version, formatted like "MAJOR.MINOR.REV".
 52//   For example, version 2.1.43 will be returned as `"2.1.43"`.
 53function bosl_version_str() = version_to_str(BOSL_VERSION);
 54
 55
 56// Module: bosl_required()
 57// Synopsis: Asserts that the current version of the library is at least the given version.
 58// Topics: Versioning
 59// See Also: version_to_num(), version_to_str(), version_to_list(), version_cmp()
 60// Usage:
 61//   bosl_required(version);
 62// Description:
 63//   Given a version as a list, number, or string, asserts that the currently installed BOSL library is at least the given version.
 64// Arguments:
 65//   version = version required
 66module bosl_required(version) {
 67    no_children($children);
 68    assert(
 69        version_cmp(bosl_version(), version) >= 0,
 70        str(
 71            "BOSL ", bosl_version_str(), " is installed, but BOSL ",
 72            version_to_str(version), " or better is required."  
 73        )
 74    );
 75}
 76
 77
 78// Section: Generic Version Functions
 79
 80function _version_split_str(x, _i=0, _out=[], _num=0) =
 81    _i>=len(x)? concat(_out,[_num]) :
 82    let(
 83        cval = ord(x[_i]) - ord("0"),
 84        numend = cval<0 || cval>9,
 85        _out = numend? concat(_out, [_num]) : _out,
 86        _num = numend? 0 : (10*_num + cval)
 87    )
 88    _version_split_str(x, _i=_i+1, _out=_out, _num=_num);
 89
 90
 91// Function: version_to_list()
 92// Synopsis: Splits a version into a list of integer version parts.
 93// Topics: Versioning
 94// See Also: version_to_num(), version_to_str(), version_cmp(), bosl_required()
 95// Usage:
 96//   ver = version_to_list(x);
 97// Description:
 98//   Given a version string, number, or list, returns the list of version integers [MAJOR,MINOR,REVISION].
 99// Arguments:
100//   x = version to convert
101// Example:
102//   v1 = version_to_list("2.1.43");  // Returns: [2,1,43]
103//   v2 = version_to_list(2.120234);  // Returns: [2,12,234]
104//   v3 = version_to_list([2,3,4]);   // Returns: [2,3,4]
105//   v4 = version_to_list([2,3,4,5]); // Returns: [2,3,4]
106function version_to_list(version) =
107    is_list(version)? [default(version[0],0), default(version[1],0), default(version[2],0)] :
108    is_string(version)? _version_split_str(version) :
109    is_num(version)? [floor(version), floor(version*100%100), floor(version*1000000%10000+0.5)] :
110    assert(is_num(version) || is_vector(version) || is_string(version)) 0;
111
112
113// Function: version_to_str()
114// Synopsis: Coerces a version into a standard version string.
115// Topics: Versioning
116// See Also: version_to_num(), version_to_list(), version_cmp(), bosl_required()
117// Usage:
118//   str = version_to_str(version);
119// Description:
120//   Takes a version string, number, or list, and returns the properly formatter version string for it.
121// Arguments:
122//   version = version to convert
123// Example:
124//   v1 = version_to_str([2,1,43]);  // Returns: "2.1.43"
125//   v2 = version_to_str(2.010043);  // Returns: "2.1.43"
126//   v3 = version_to_str(2.340789);  // Returns: "2.34.789"
127//   v4 = version_to_str("2.3.89");  // Returns: "2.3.89"
128function version_to_str(version) =
129    let(version = version_to_list(version))
130    str(version[0],".",version[1],".",version[2]);
131
132
133// Function: version_to_num()
134// Synopsis: Coerces a version into a standard version float.
135// Topics: Versioning
136// See Also: version_cmp(), version_to_str(), version_to_list(), bosl_required()
137// Usage:
138//   str = version_to_num(version);
139// Description:
140//   Takes a version string, number, or list, and returns the properly formatter version number for it.
141// Arguments:
142//   version = version to convert
143// Example:
144//   v1 = version_to_num([2,1,43]);   // Returns: 2.010043
145//   v2 = version_to_num([2,34,567]); // Returns: 2.340567
146//   v3 = version_to_num(2.120567);   // Returns: 2.120567
147//   v4 = version_to_num("2.6.79");   // Returns: 2.060079
148function version_to_num(version) =
149    let(version = version_to_list(version))
150    (version[0]*1000000 + version[1]*10000 + version[2])/1000000;
151
152
153// Function: version_cmp()
154// Synopsis: Compares two versions.
155// Topics: Versioning
156// See Also: version_to_num(), version_to_str(), version_to_list(), bosl_required()
157// Usage:
158//   cmp = version_cmp(a,b);
159// Description:
160//   Given a pair of versions, in any combination of string, integer, or list, compares them, and returns the relative value of them.
161//   Returns an integer <0 if a<b.  Returns 0 if a==b.  Returns an integer >0 if a>b.
162// Example:
163//   cmp1 = version_cmp(2.010034, "2.1.33");  // Returns: >0
164//   cmp2 = version_cmp(2.010034, "2.1.34");  // Returns: 0
165//   cmp3 = version_cmp(2.010034, "2.1.35");  // Returns: <0
166function version_cmp(a,b) =
167    let(
168        a = version_to_list(a),
169        b = version_to_list(b),
170        cmps = [for (i=[0:1:2]) if(a[i]!=b[i]) a[i]-b[i]]
171    ) cmps==[]? 0 : cmps[0];
172
173
174// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap